package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.constant.Constants;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.FaultReportDTO;
import com.tbit.uqbike.object.pojo.vo.MachineFaultLogVo;
import com.tbit.uqbike.object.pojo.vo.MachineFaultPersonVo;
import com.tbit.uqbike.object.pojo.vo.MachineFaultRecordVO;
import com.tbit.uqbike.object.pojo.vo.MachineFaultVehicleVo;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.AccountConfigService;
import com.tbit.uqbike.service.business.FaultReportService;
import com.tbit.uqbike.service.business.ImageService;
import com.tbit.uqbike.webmanager.dao.core.AccountConfigExtDao;
import com.tbit.uqbike.webmanager.dao.core.MachineDao;
import com.tbit.uqbike.webmanager.dao.core.MachineFaultDao;
import com.tbit.uqbike.webmanager.dao.core.UserDao;
import com.tbit.uqbike.webmanager.dao.log.FaultReportDao;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.DateTimeUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author LHX
 * @ClassName FaultReportServiceImpl
 * @Description
 * @date 2023/5/18 15:42
 * @Version 1.0
 */
@Service
public class FaultReportServiceImpl implements FaultReportService {

    @Autowired
    private FaultReportDao faultReportDao;
    @Autowired
    private ImageService imageService;
    @Autowired
    AccountConfigService accountConfigService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MachineFaultDao machineFaultDao;
    @Resource
    private MachineDao machineDao;

    @Override
    public PageResult<MachineFaultLogVo> queryPageDetails(FaultReportDTO faultReportDTO) {
        faultReportDTO.parseFaults();
        PageInfo<MachineFaultLogVo> pageInfo;
        if (Objects.nonNull(faultReportDTO.getIntoMain())) {
            pageInfo = PageMethod.startPage(faultReportDTO.getPage(), faultReportDTO.getSize()).doSelectPageInfo(() -> faultReportDao.queryPageDetailsNew(faultReportDTO));
            for (MachineFaultLogVo machineFaultLogVo : pageInfo.getList()) {
                machineFaultLogVo.analysis();
            }
        } else {
            pageInfo = PageMethod.startPage(faultReportDTO.getPage(), faultReportDTO.getSize()).doSelectPageInfo(() -> faultReportDao.queryPageDetails(faultReportDTO));
        }
        List<MachineFaultLogVo> list = pageInfo.getList();
        list.forEach(MachineFaultLogVo::parseFaults);
        return new PageResult<>(faultReportDTO.getPage(), faultReportDTO.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Result exportDetails(FaultReportDTO faultReportDTO) {
        faultReportDTO.setPage(1);
        faultReportDTO.setSize(65535);
        PageResult<MachineFaultLogVo> pageResult = queryPageDetails(faultReportDTO);
        List<MachineFaultLogVo> list = pageResult.getList();
        ExcelUtil<MachineFaultLogVo> excelUtil = new ExcelUtil<>(MachineFaultLogVo.class);
        JsonResult jsonResult = excelUtil.exportExcel(list, "故障上报统计详情");
        return Result.success(jsonResult.getData());
    }

    @Override
    public PageResult<MachineFaultVehicleVo> queryPageVehicle(FaultReportDTO faultReportDTO) {
        PageInfo<MachineFaultVehicleVo> pageInfo = PageMethod.startPage(faultReportDTO.getPage(), faultReportDTO.getSize()).doSelectPageInfo(() -> faultReportDao.queryPageVehicle(faultReportDTO));
        return new PageResult<>(faultReportDTO.getPage(), faultReportDTO.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Result exportVehicle(FaultReportDTO faultReportDTO) {
        faultReportDTO.setPage(1);
        faultReportDTO.setSize(65535);
        PageResult<MachineFaultVehicleVo> pageResult = queryPageVehicle(faultReportDTO);
        List<MachineFaultVehicleVo> list = pageResult.getList();
        ExcelUtil<MachineFaultVehicleVo> excelUtil = new ExcelUtil<>(MachineFaultVehicleVo.class);
        JsonResult jsonResult = excelUtil.exportExcel(list, "故障上报车辆总览");
        return Result.success(jsonResult.getData());
    }

    @Override
    public PageResult<MachineFaultPersonVo> queryPagePerson(FaultReportDTO faultReportDTO) {
        PageInfo<MachineFaultPersonVo> pageInfo = PageMethod.startPage(faultReportDTO.getPage(), faultReportDTO.getSize()).doSelectPageInfo(() -> faultReportDao.queryPagePerson(faultReportDTO));
        return new PageResult<>(faultReportDTO.getPage(), faultReportDTO.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());

    }

    @Override
    public Result exportPerson(FaultReportDTO faultReportDTO) {
        faultReportDTO.setPage(1);
        faultReportDTO.setSize(65535);
        PageResult<MachineFaultPersonVo> pageResult = queryPagePerson(faultReportDTO);
        List<MachineFaultPersonVo> list = pageResult.getList();
        ExcelUtil<MachineFaultPersonVo> excelUtil = new ExcelUtil<>(MachineFaultPersonVo.class);
        JsonResult jsonResult = excelUtil.exportExcel(list, "故障上报人员总览");
        return Result.success(jsonResult.getData());
    }

    @Override
    public Result exportRecord(FaultReportDTO faultReportDTO) {
        faultReportDTO.setPage(1);
        faultReportDTO.setSize(Integer.MAX_VALUE);
        PageResult<MachineFaultLogVo> pageResult = queryPageDetails(faultReportDTO);
        List<MachineFaultLogVo> list = pageResult.getList();
        List<MachineFaultRecordVO> excelList = list.stream().map(item -> {
            MachineFaultRecordVO vo = new MachineFaultRecordVO();
            BeanUtils.copyProperties(item, vo);
            return vo;
        }).collect(Collectors.toList());
        ExcelUtil<MachineFaultRecordVO> excelUtil = new ExcelUtil<>(MachineFaultRecordVO.class);
        JsonResult jsonResult = excelUtil.exportExcel(excelList, "故障上报处理记录");
        return Result.success(jsonResult.getData());
    }

    @Override
    public void insert(MultipartFile[] files, MachineFault machineFault, HttpServletRequest request, LoginInfo loginInfo, Machine machine,Integer brandId,String userPhone) throws Exception {
        Map<String, Object> getByAccountIdAndPhoneMap = new HashMap<String, Object>();
        getByAccountIdAndPhoneMap.put("phone", userPhone);
        getByAccountIdAndPhoneMap.put("accountId", brandId);
        List<User> byAccountIdAndPhone = userDao.getByAccountIdAndPhone(getByAccountIdAndPhoneMap);
        if(null == byAccountIdAndPhone || byAccountIdAndPhone.size() <1){
            throw new BaseException( "您输入的用户不存在，请重新检查并输入正确的号码");
        }
        if ( machineFault.getRemark().length() > 50){
            throw new BaseException("备注不能超过50字");
        }
        User user = byAccountIdAndPhone.get(0);
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        StringBuffer name = new StringBuffer();
        /* 判断是否是文件上传 */
        if (ArrayUtil.isNotEmpty(files)) {
            if(files.length > 3){
                throw new BaseException("图片最多只能上传三张");
            }
            for (MultipartFile file : files) {
                if (file.getSize() > 2 * 1024 * 1024) {
                    throw new BaseException("图片过大");
                }
                String fileName = imageService.uploadImage( brandId,file, null);
                name.append(fileName).append(";");
            }
        }

        if (name.length() > 1) {
            name.delete(name.length() - 1, name.length());
        }
        //查询该车辆最新的一条故障上报记录
        MachineFaultLog newestMachineFaultLog = faultReportDao.selectNewestLog(machine.getMachineId());
        String orderNO = IdUtil.objectId();
        if (newestMachineFaultLog != null && StringUtils.hasText(newestMachineFaultLog.getOrderNO()) && !newestMachineFaultLog.getFaulttype().equals(4)) {
            orderNO = newestMachineFaultLog.getOrderNO();
        }
        String nowTime = DateTimeUtil.getNowTime();
        machineFault.setUpdateTime(DateUtil.parse(nowTime, "yyyy-MM-dd HH:mm:ss"));
        machineFault.setImageIds(name.toString());
        MachineFaultLog machineFaultLog = new MachineFaultLog();
        machineFaultLog.setAccountId(machine.getAccountId())
                .setMachineId(machine.getMachineId())
                .setUserCode(machine.getUserCode())
                .setAddManid(user.getUserId())
                .setAddManName(user.getName())
                .setAddManPhone(user.getPhone())
                .setAddTime(DateUtil.parse(nowTime, "yyyy-MM-dd HH:mm:ss"))
                .setFaults(machineFault.getFaults())
                .setImageIds(name.toString())
                .setIntoMain(1)
                .setPoint(machineFault.getPoint())
                .setFaulttype(5)
                .setMachineType(machine.getMachineType())
                .setRemark("管理员名称("+loginInfo.getName()+");备注内容:"+machineFault.getRemark())
                .setOrderNO(orderNO)
                .setUserPhone(loginInfo.getPhone());
        faultReportDao.insert(machineFaultLog);
        //兼容用户x天内上报y次故障车辆是否可再次借出
        AccountConfig accountConfig = accountConfigService.getByAccountId(loginInfo,machine.getAccountId());
        if (accountConfig != null) {
            AccountConfigExt dayConfigExt = getAccountConfigExtByKey(machine.getAccountId(), Constants.USER_SIGN_FAULT_DAY);
            AccountConfigExt countConfigExt = getAccountConfigExtByKey(machine.getAccountId(), Constants.USER_SIGN_FAULT_COUNT);
            if (dayConfigExt == null || countConfigExt == null) {
                //兼容旧数据，给默认值
                dayConfigExt = new AccountConfigExt(machine.getAccountId(), Constants.USER_SIGN_FAULT_DAY, "30", null, null);
                countConfigExt = new AccountConfigExt(machine.getAccountId(), Constants.USER_SIGN_FAULT_COUNT, "5", null, null);
            }
            //满足条件且实时表没有则添加到实时表
            if (Integer.parseInt(dayConfigExt.getParamValue()) > 0) {
                Integer count = faultReportDao.getCountByMachineIdAndDay(machineFault.getMachineId(), Integer.parseInt(dayConfigExt.getParamValue()), Integer.parseInt(countConfigExt.getParamValue()));
                if (count > 0) {
                    //machineFaultDao.getByMachineId(machineFault.getMachineId());
                    MachineFault machineFaultInDb = this.checkMachineSuspectedFault(machineFault.getMachineId());
                    if ( null ==  machineFaultInDb ) {
                        machineFault.setOrderNO(orderNO);
                        machineFaultDao.insertMachineFault(machineFault);
                    }
                }
            }
        }

    }

    /**
     * 恢复为正常状态
     * @param machineId 车辆id
     * @return Result
     */
    @Override
    public Result<Object> backToNormal(Integer machineId) {
        machineFaultDao.del(machineId);
        machineDao.updateNormalById(machineId);
        return Result.success();
    }

    public AccountConfigExt getAccountConfigExtByKey(Integer accountId, String key) {
        List<AccountConfigExt> accountConfigExts = getAccountConfigExt(accountId);
        if (accountConfigExts.size() > 0) {
            for (AccountConfigExt a : accountConfigExts) {
                if (a.getParamKey().equals(key)) {
                    return a;
                }
            }
        }
        return null;
    }

    public List<AccountConfigExt> getAccountConfigExt(Integer accountId) {
        String value = redisService.get(Constants.ACCOUNTCONFIG_KEY_PREFIX + accountId);
        List<AccountConfigExt> accountConfigExt = null;
        if (value == null) {
            accountConfigExt = accountConfigExtDao.getByAccountIdClass(accountId);
            if (accountConfigExt != null) {
                /**放入redis,有效期5分钟*/
                redisService.add(Constants.ACCOUNTCONFIG_KEY_PREFIX + accountId, JSON.toJSONString(accountConfigExt), 300);
            }
        } else {
            accountConfigExt = JSON.parseArray(value, AccountConfigExt.class);
        }
        return accountConfigExt;
    }

    /**
     * @description: 检查故障是否是疑似故障，如果是疑似故障则删除掉疑似故障，把正式的故障加入
     * @author: mo.shanyong
     * @date: 2025/5/13 17:05
     * @param: machineId
     * @return: com.tbit.uqbike.object.pojo.MachineFault
     */
    private MachineFault checkMachineSuspectedFault(Integer machineId){
        MachineFault machineFaultInDb = machineFaultDao.getByMachineId(machineId);
        //故障为空，或者不是疑似故障，则直接返回
        if (Objects.isNull(machineFaultInDb) || !Objects.equals(machineFaultInDb.getFrom(),4)){
            return machineFaultInDb;
        }
        machineFaultDao.del(machineFaultInDb.getMachineId());
        return null;
    }



}
